package com.sqx.common.aspect;

import com.google.gson.Gson;
import com.sqx.common.utils.DateUtils;
import com.sqx.common.utils.HttpContextUtils;
import com.sqx.common.utils.IPUtils;
import com.sqx.common.annotation.SysLog;
import com.sqx.modules.app.utils.JwtUtils;
import com.sqx.modules.log.entity.SysLogLoginEntity;
import com.sqx.modules.log.entity.SysLogOperationEntity;
import com.sqx.modules.log.service.SysLogLoginService;
import com.sqx.modules.log.service.SysLogOperationService;
import com.sqx.modules.sys.entity.SysLogEntity;
import com.sqx.modules.sys.entity.SysUserEntity;
import com.sqx.modules.sys.service.SysLogService;
import com.sqx.modules.utils.IpUtils;
import com.sqx.modules.utils.JsonUtils;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;


/**
 * 系统日志，切面处理类
 *
 */
@Aspect
@Component
public class SysLogAspect {

	@Autowired
	private SysLogOperationService sysLogOperationService;

	@Autowired
	private SysLogLoginService sysLoginService;

	@Autowired
	private JwtUtils jwtUtils;

	@Pointcut("@annotation(com.sqx.common.annotation.SysLog)")
	public void logPointCut() {

	}

	@Around("logPointCut()")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		long beginTime = System.currentTimeMillis();
		try {
			//执行方法
			Object result = point.proceed();

			//执行时长(毫秒)
			long time = System.currentTimeMillis() - beginTime;
			//保存日志
			saveSysLog(point, time, 1);

			return result;
		} catch (Exception e) {
			//执行时长(毫秒)
			long time = System.currentTimeMillis() - beginTime;
			//保存日志
			saveSysLog(point, time, 0);

			throw e;
		}
	}
	private void saveSysLog(ProceedingJoinPoint joinPoint, long time,Integer status) {
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();

		SysLog syslog = method.getAnnotation(SysLog.class);

		SysLogOperationEntity log = new SysLogOperationEntity();
		if(syslog != null){
			//注解上的描述
			log.setOperation(syslog.value());
			log.setUserType(syslog.type());
		}

		//登录用户信息
		try {
			SysUserEntity user = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
			if (user != null) {
				log.setCreatorName(user.getUsername());
			}
		}catch (Exception e){
			e.printStackTrace();
		}


		log.setStatus(status);
		log.setRequestTime((int) time);

		//请求相关信息
		HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
		//从request获取token信息 获取用户id
		Long userId=null;
		String token = request.getHeader(jwtUtils.getHeader());
		if(StringUtils.isBlank(token)){
			token = request.getParameter(jwtUtils.getHeader());
		}
		if(StringUtils.isNotEmpty(token)){
			Claims claims = jwtUtils.getClaimByToken(token);
			if(claims!=null){
				userId = Long.parseLong(claims.getSubject());
			}
		}else{
				SysLogLoginEntity logLoginEntity = new SysLogLoginEntity();
				logLoginEntity.setOperation(syslog.value());
				logLoginEntity.setStatus(status);
				logLoginEntity.setIp(IpUtils.getIpAddr(request));
				logLoginEntity.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
				logLoginEntity.setCreateTime(DateUtils.format(new Date()));
				//请求参数
				Object[] args = joinPoint.getArgs();
				String params = JsonUtils.toJsonString(args[0]);
				logLoginEntity.setCreatorName(params);
				sysLoginService.save(logLoginEntity);
		}
		log.setUserId(userId);
		log.setIp(IpUtils.getIpAddr(request));
		log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
		log.setRequestUri(request.getRequestURI());
		log.setRequestMethod(request.getMethod());
		log.setCreateTime(DateUtils.format(new Date()));
		//请求参数
		Object[] args = joinPoint.getArgs();
		try {
			String params = JsonUtils.toJsonString(args[0]);
			log.setRequestParams(params);
		} catch (Exception e) {

		}
		//保存到DB
		sysLogOperationService.save(log);
	}
}
